<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style>
        html, body {
            width: 100%;
            height: 100%;
            margin: 0;
            padding: 0;
        }

        canvas {
            position: absolute;
            top: 0;
            left: 0;
            width: 100%;
            height: 100%;
        }
    </style>
</head>
<body>
<canvas id="c"></canvas>
<script>
    var c = document.getElementById('c'),
      w = c.width = window.innerWidth,
      h = c.height = window.innerHeight,
      tric = 0,
      lines = [],
      ctx = c.getContext('2d'),
      opts = {
          cx: w / 2,
          cy: h / 2,
          baseTimes: 10,
          addedTimes: 30,
          color: 'hsl(hue,100%,light%)',
          sparkRange: 20,
          sparkSize: 2,
          sparkLimit:0.03,
          deg: 2 * Math.PI / 6,
          pointWidth: 2,
          pointHeight:2,
          len: 20,
          repaintAlpha: .04,
          hueChange:0.1,
          baseLight:50,
          addedLight:-0.02,
          baseHue:0,
          addedHue:1,
          lightChange:0.1,
          dieLimit:0.1,
          lenLimit:500,
          lineCount: 1000,
          shadowUnit:6,
      };

    var line = function () {
        this.pointWidth = opts.pointWidth;
        this.pointHeight = opts.pointHeight;
        this.reset();
    }

    line.prototype.reset = function () {
        this.x = 0;
        this.y = 0;
        this.dx = 0;
        this.dy = 0;
        this.deg =  0;
        this.light = opts.baseLight;
        if(this.hue === undefined){
            this.hue = opts.baseHue
        }else{
            this.hue += opts.addedHue;
        }
        this.beginPhase();

    }

    line.prototype.beginPhase = function () {
        var deg = opts.deg * (Math.random() > 0.5 ? 1 : -1);

        this.deg += deg ;
        this.x += (this.dx || 0);
        this.y += (this.dy || 0);
        this.dx = Math.cos(this.deg)  * opts.len ;
        this.dy = Math.sin(this.deg)  * opts.len;


        this.times = 0;

        this.targetTimes = opts.baseTimes + Math.random() * opts.addedTimes;



        var len = Math.sqrt(this.x * this.x + this.y * this.y);
        if (Math.random() < opts.dieLimit || len > opts.lenLimit) {
            this.reset();
        }
    }


    line.prototype.step = function () {

        if (this.times > this.targetTimes) {
            this.beginPhase();
        }

        var wave = Math.sin(this.times / this.targetTimes * Math.PI / 2),
          x = opts.cx + this.x + this.dx * wave,
          y = opts.cy + this.y + this.dy * wave;

        this.times++;
        this.light+= opts.addedLight;

        if(Math.random() < opts.sparkLimit){
            var sx = x + Math.cos(Math.random() * Math.PI * 2) * opts.sparkRange * Math.random(),
                sy = y + Math.cos(Math.random() * Math.PI * 2) * opts.sparkRange * Math.random();

            ctx.fillRect(sx,sy,opts.sparkSize,opts.sparkSize);
        }

        ctx.shadowBlur  = wave * opts.shadowUnit;
        ctx.fillStyle = ctx.shadowColor = opts.color.replace('hue',this.hue).replace('light',this.light);
        ctx.fillRect(x, y, this.pointWidth, this.pointHeight);
        ctx.fill();

    }


    function loop() {
        tric ++ ;
        window.requestAnimationFrame(loop);
        drawBg();
        if (lines.length < opts.lineCount) {
            lines.push(new line());
        }
        lines.map(function (line) {
            line.step();

        })


    }

    function drawBg(){
        ctx.globalCompositeOperation = 'source-over';
        ctx.shadowBlur = 0;
        ctx.fillStyle = 'rgba(0,0,0,alp)'.replace('alp', opts.repaintAlpha);
        ctx.fillRect(0, 0, w, h);
    }


    loop();


</script>
</body>
</html>